<template>
  <teleport to="body">
    <div v-if="visible" class="ttt-popup-bg" :style="{ zIndex }" @click="handleClick('close',true)"></div>
  </teleport>
  <teleport to="body">
    <transition :name="position">
      <div v-if="visible" class="ttt-popup" :class="[position]" :style="popupStyle">
        <slot name="title">
          <div class="ttt-popup-title" v-if="title">{{ title }}</div>
        </slot>
        <div class="content" :class="{padding: isPadding}">
          <slot name="default" />
        </div>
      </div>
    </transition>
  </teleport>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { getZIndex } from '../utils/utils'
import { TLoading } from '../directive/TLoading/TGlobalLoading'
import type { PropType, CSSProperties } from 'vue'
import type { TPopupBeforeCloseParams } from '../types/components'

const emits = defineEmits<{
  (e: 'close', value: boolean): void
  (e: 'update:modelValue', value: boolean): void
}>()

const props = defineProps({
  // 绑定数据
  modelValue: {
    type: Boolean as PropType<boolean>,
    required: true
  },
  // 标题 不填标题则没有标题
  title: {
    type: String as PropType<string>,
    default: ''
  },
  // 方向
  position: {
    type: String as PropType<'left' | 'right' | 'top' | 'bottom'>,
    default: 'bottom'
  },
  // 宽度
  width: {
    type: [String, Number] as PropType<string | number>,
    default: '80%'
  },
  // 是否需要padding间距 默认需要
  isPadding: {
    type: Boolean as PropType<boolean>,
    default: true
  },
  // 是否点击模态窗关闭
  closeModal: {
    type: Boolean as PropType<boolean>,
    default: true
  },
  // 关闭之前
  beforeClose: {
    type: Function as PropType<TPopupBeforeCloseParams>,
    default: null
  }
})

const zIndex = ref<number>(getZIndex())
const visible = ref<boolean>(props.modelValue)
const popupStyle = computed<CSSProperties>((): CSSProperties => {
  const size = Number.isNaN(Number(props.width)) ? props.width : `${props.width}rem`
  const row = props.position === 'left' || props.position === 'right'
  const col = props.position === 'top' || props.position === 'bottom'
  const width = row ? size : '100%'
  const height = col ? size : '100%'
  const position = props.position === 'right' ? { left: 'unset' } : props.position === 'left' ? { right: 'unset' } : props.position === 'top' ? { bottom: 'unset' } : { top: 'unset' }
  return {
    width: String(width),
    height: String(height),
    inset: '0',
    ...position,
    zIndex: String(zIndex.value)
  }
})

const handleClick = (type: 'close', isModal: boolean = false) => {
  if (isModal && !props.closeModal) return
  if (props.beforeClose && typeof props.beforeClose === 'function') {
    const loading = TLoading()
    props.beforeClose((confirm: boolean): void => {
      if (confirm) {
        loading.close()
        visible.value = false
        emits('close', true)
        emits('update:modelValue', false)
      }
    })
    return
  }
  visible.value = false
  emits('close', true)
  emits('update:modelValue', false)
}

watch(() => props.modelValue, (val: boolean) => {
  visible.value = val
})
</script>

<style scoped lang="scss">
.ttt-popup-bg {
  position: fixed;
  inset: 0;
  background-color: var(--theme-modal);
}

.ttt-popup {
  position: fixed;
  background-color: var(--theme-bg);

  &.bottom-enter-active, &.bottom-leave-active {
    transform: translate3d(0, 0, 0);
    transition: all 0.3s;
  }

  &.bottom-enter-from, &.bottom-leave-to {
    transform: translate3d(0, 100%, 0);
  }

  &.top-enter-active, &.top-leave-active {
    transform: translate3d(0, 0, 0);
    transition: all 0.3s;
  }

  &.top-enter-from, &.top-leave-to {
    transform: translate3d(0, -100%, 0);
  }

  &.left-enter-active, &.left-leave-active {
    transform: translate3d(0, 0, 0);
    transition: all 0.3s;
  }

  &.left-enter-from, &.left-leave-to {
    transform: translate3d(-100%, 0, 0);
  }

  &.right-enter-active, &.right-leave-active {
    transform: translate3d(0, 0, 0);
    transition: all 0.3s;
  }

  &.right-enter-from, &.right-leave-to {
    transform: translate3d(100%, 0, 0);
  }

  &.left {
    border-radius: 0 var(--modal-rudias) var(--modal-rudias) 0;
  }

  &.right {
    border-radius: var(--modal-rudias) 0 0 var(--modal-rudias);
  }

  &.top {
    border-radius: 0 0 var(--modal-rudias) var(--modal-rudias);
  }

  &.bottom {
    border-radius: var(--modal-rudias) var(--modal-rudias) 0 0;
  }

  .ttt-popup-title {
    font-size: 32rem;
    font-weight: bolder;
    padding: 20rem;
  }

  .content {
    &.padding {
      padding: 0 20rem;
    }
  }
}
</style>
